#! /usr/bin/perl -w
#---------------------------------------------------------------------------------
#  make_fare.pl is part of the BART dashboard widget.  (c) 2008 Bret Victor
#  This software is licensed under the terms of the open source MIT license.
#---------------------------------------------------------------------------------
#
#  perl make_timetables.pl -fare > Fare.js
#
#  Downloads the line schedules from bart.gov and generates a JavaScript
#  fare table on stdout.  This becomes the Fare.js file.
#


use strict;

#-----------------------------------------------------------------
#  Tables

my %station_names = (

    'MLBR' => "Millbrae",
    'SFIA' => "SFO",
    'SBRN' => "San Bruno",
    'SSAN' => "South SF",
    'COLMA' => "Colma",
    
    'DALY' => "Daly City",
    'BALPK' => "Balboa Park",
    
    'WOAK' => "West Oakland",
    'EMBAR' => "Embarcadero", 
    'MONTG' => "Montgomery", 
    'POWEL' => "Powell", 
    'CIVIC' => "Civic Center",
    '16ST' => "16th St",
    '24ST' => "24th St",

    'BAYPT' => "Pittsburg", 
    'NCNC' => "North Concord",
    'CONCD' => "Concord", 
    'PHILL' => "Pleasant Hill",
    'WCRK' => "Walnut Creek",
    'LAFAY' => "Lafayette", 
    'ORNDA' => "Orinda", 
    'ROCKR' => "Rockridge", 
    'MACAR' => "MacArthur",
    '12ST' => "12th St",
    '19ST' => "19th St",
    
    'HAY' => "Hayward", 
    'SHAY' => "South Hayward",
    'UCITY' => "Union City",
    'FREMT' => "Fremont",

    'LAKEM' => "Lake Merritt", 
    'FRTVL' => "Fruitvale", 
    'COLIS' => "Coliseum",
    'SLEAN' => "San Leandro",
    'BFAIR' => "Bay Fair",
    
    'RICH' => "Richmond", 
    'DELN' => "Del Norte", 
    'PLAZA' => "Plaza", 
    'NBRK' => "North Berkeley",
    'BRK' => "Berkeley", 
    'ASHBY' => "Ashby",
    
    'GLNPK' => "Glen Park",
    'CVLY' => "Castro Valley",
    'DUBLIN' => "Dublin",

);


#-----------------------------------------------------------------
#  Main code

my %fares;

for my $from_station (sort keys %station_names) {
    warn "from $station_names{$from_station}...\n";
    for my $to_station (sort keys %station_names) {
        my $url = makeUrl($from_station, $to_station);
        my $html = getFromUrl($url);
        my $fare = getFareFromHtml($html);
        $fares{$station_names{$from_station}}{$station_names{$to_station}} = $fare;
    }
}
print getJavascript(\%fares);
exit();


#-----------------------------------------------------------------
#  Main subroutines

sub makeUrl {
    my ($from_station, $to_station) = @_;
    return "http://bart.gov/tickets/calculator/fareCalculator.asp?trip_mode=oneway&origin=$from_station" .
           "&destination=$to_station&Submit.x=1&Submit.y=1&Submit=submit&dhtml=0";
}

sub getFromUrl {
    my ($url) = @_;
    # I'd rather use LWP, but I can't get CPAN to work.
    return `wget --quiet -O - '$url'`;
}

sub getFareFromHtml {
    my ($html) = @_;
    my ($dollars,$cents) = ($html =~ /\.<b class="normal">\s*\$(\d+)\.(\d+)/);
    unless (defined $dollars) {
        ($dollars,$cents) = ($html =~ /\$(\d+)\.(\d+) Excursion Fare/i);
        unless (defined $dollars) { die "could not understand this:\n\n$html\n"; }
    }
    return 100 * $dollars + $cents;
}

#-----------------------------------------------------------------
#  JavaScript output generation

sub getJavascript {
    my ($fares) = @_;
    my $now = localtime;
    
    my @fare_list;
    my @station_names = sort values %station_names;
    my $number_of_stations = @station_names;
    
    for my $from_station (@station_names) {
        for my $to_station (@station_names) {
            push @fare_list, $fares->{$from_station}{$to_station};
        }
    }
    
    my $fare_string = join(", ", @fare_list);
    my $station_string = '"' . join('", "', @station_names) . '"';
    
    return <<_EOT_;
//-----------------------------------------------------------------------------
//  Fare.js is part of the BART dashboard widget.       (c) 2008 Bret Victor
//  This software is licensed under the terms of the open source MIT license.
//-----------------------------------------------------------------------------
//
//  Automatically generated by make_fare.pl on $now.
//
//  cents = Fare.getCentsBetween("Del Norte", "Castro Valley")
//

function Fare () {

    var fares = [ $fare_string ];
    
    var station_names = [ $station_string ];

    var station_indexes = {}
    for (var i=0; i < station_names.length; i++) {
        station_indexes[ station_names[i] ] = i
    }
    
    Fare.getCentsBetween = function (start_name, end_name) {
        var start_index = station_indexes[start_name]
        var end_index   = station_indexes[end_name]
        return fares[ start_index * $number_of_stations + end_index ]
    }
}

// Open the package.
Fare();

_EOT_
}

